package com.example.filelock.utils;

import android.app.AlertDialog;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.example.filelock.R;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import androidx.annotation.NonNull;

public class LoadingFile {

    private final View loadingView;     //实例的加载视图
    private final ProgressBar pb_pro;   //实例的加载视图中的加载条
    private TextView tv_msg;          //实例的加载提示文字
    private final AlertDialog logoDialog;   //实例的加载框
    private final int LOADING_PRO = 0x11;       //加载命令
    private final int LOADING_OK = 0x12;       //加载完成命令
    private final int LOADING_NOT = 0x02;       //加载失败
    final int byteLen = 1024;                   //每次读取字节个数
    private Context context;               //上下文

    Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            try {
                if (msg.what == LOADING_PRO) {
                    //加载命令
                    if (pb_pro != null)
                        pb_pro.setProgress(msg.arg1);
                } else if (msg.what == LOADING_OK) {
                    //加载完成
                    if (logoDialog != null) {
                        //提示3:
                        tv_msg.setText("加密完成");
                        logoDialog.cancel();
                        if (loadingFileOk != null)
                            loadingFileOk.onLoadingOk();
                    }
                } else if (msg.what == LOADING_NOT) {
                    //密码不正确
                    if (logoDialog != null) {
                        //提示3:
                        tv_msg.setText("加密失败");
                        logoDialog.cancel();
                        Toast.makeText(context, (String) msg.obj, Toast.LENGTH_SHORT).show();
                    }
                }
                //提示文字
                if (msg.obj != null)
                    tv_msg.setText(String.valueOf(msg.obj));
            }catch (Exception e){
                Log.d(BasDataUtil.LOG_TOAST,"核心Message错误:"+e.toString());
            }


        }
    };
    //加载完成回调
    LoadingFileOk loadingFileOk = null;

    public interface LoadingFileOk {
        void onLoadingOk();
    }

    public void addLoadingOk(LoadingFileOk loadingFileOk) {
        this.loadingFileOk = loadingFileOk;
    }

    //    构造方法
    public LoadingFile(Context context, long loadingLen) {
        //        初始化文件夹
        FileUtil.initMainFile(context);
        this.context = context;
        loadingView = LayoutInflater.from(context).inflate(R.layout.loding_view, null);
        pb_pro = loadingView.findViewById(R.id.loading_pb);
        tv_msg = loadingView.findViewById(R.id.loading_tv_msg);
        logoDialog = new AlertDialog.Builder(context)
                .setCancelable(false)
                .setView(loadingView)
                .show();
        //初始化加载条
        while (loadingLen > Integer.MAX_VALUE)    //一定不能>int
            loadingLen = loadingLen / byteLen;
        pb_pro.setMax((int) (loadingLen));  //设置传入的文件长度
    }

    //    加密操作
    public boolean encryptionFile(final String redPath, final String redPwd) {
        final File redFile = new File(redPath);
        if (!redFile.exists() || redFile.length() == 0) {
            //如果没有此文件，并文件内容为空
            if (logoDialog != null)
                logoDialog.cancel();
            return false;
        }
        new Thread() {
            @Override
            public void run() {
                try {
                    //初始化使用的变量
                    final byte[] buf = new byte[byteLen];   //设置读取字节
                    SimpleDateFormat dateFormat = new SimpleDateFormat("(yyyyMMddhhmmss)");
                    int len = 0;    //加载字节
                    int pro = 0;    //一共加载了多少字节
                    Message message;    //消息传递实例
                    //提示1:
                    message = new Message();
                    message.obj = "正在压缩中,建议不要中途退出....";
                    handler.sendMessage(message);
                    //1.压缩文件：这里可能需要点时间，会卡住，但是在Thread异步里，不必担心
                    FileZipUtil.zipFile(redPath, BasDataUtil.getEncryptionPath() + "/" + BasDataUtil.FILE_NAME_TEM);
                    final InputStream inputStream = new FileInputStream(BasDataUtil.getEncryptionPath() + "/" + BasDataUtil.FILE_NAME_TEM);
                    //返回自己定义的文件名即可
                    final OutputStream outputStream = new FileOutputStream(new File(BasDataUtil.getEncryptionPath() + "/t_" + FileUtil.getFileNameNoEx(redFile.getName()) + dateFormat.format(new Date()) + ".t"));
                    //加密1：获取输入密码
                    String pwd = redPwd;
                    //补齐密码
                    StringBuilder remPwd = new StringBuilder();
                    for (int i = pwd.length()-1; i < 5; i++) {
                        remPwd.append("t");
                    }
                    String newPwd = BasDataUtil.PWD_HE+remPwd+ FileZipUtil.setFilePwd(pwd.toString()) + BasDataUtil.PWD_HE;
                    //加密2：将密码加密后藏入
                    outputStream.write(newPwd.getBytes());
                    //2.修改文件：进行加密处理
                    //提示2:
                    message = new Message();
                    message.obj = "正在加密中，文件越大加密越久，请耐心等待...";
                    handler.sendMessage(message);
                    while ((len = inputStream.read(buf)) != -1) {
                        sleep(1);
                        //加密3：进行加密算法
                        for (int i = 0; i < buf.length; i++) {
                            if (i % 2 == 0) {
                                buf[i] = (byte) (buf[i] + (10 + Integer.parseInt(pwd.charAt(0) + "")));
                            } else {
                                buf[i] = (byte) (buf[i] + (Integer.parseInt(pwd.charAt(pwd.length() - 1) + "")));
                            }
                        }
                        //写入加密后的文件
                        outputStream.write(buf, 0, len);
                        //记录加载的长度
                        pro += 1024;
                        //进行消息传递，并以进度条显示
                        message = new Message();
                        message.what = LOADING_PRO;
                        message.arg1 = pro;
                        handler.sendMessage(message);
                    }
                    //出了while就是加密完成，关闭输入流
                    inputStream.close();
                    outputStream.close();
                    //3.删除临时文件
                    File temFile = new File(BasDataUtil.getEncryptionPath() + "/" + BasDataUtil.FILE_NAME_TEM);
                    if (temFile.exists()) {
                        temFile.delete();
                    }
                    message = new Message();
                    message.what = LOADING_OK;
                    handler.sendMessage(message);
                    Log.d(BasDataUtil.LOG_TOAST, "加密完成");
                } catch (Exception e) {
                    Message message = new Message();
                    message.what = LOADING_NOT;
                    message.obj = "没有权限，或忘记损坏!";
                    handler.sendMessage(message);
                    Log.d(BasDataUtil.LOG_TOAST, "加密过程错误:" + e.toString());
                }
            }
        }.start();
        return true;
    }

    //    解密操作
    public boolean decryptionFile(final String redPath, final String redPwd) {
        final File redFile = new File(redPath);
        if (!redFile.exists() || redFile.length() == 0) {
            //如果没有此文件，并文件内容为空
            if (logoDialog != null)
                logoDialog.cancel();
            return false;
        }
        new Thread() {
            @Override
            public void run() {
                try {
                    //初始化使用的变量
                    final byte[] buf = new byte[byteLen];   //设置读取字节
                    byte[] temBuf = new byte[28];       //密码字节
                    int len = 0;    //加载字节
                    int pro = 0;    //一共加载了多少字节
                    String outFileName = FileUtil.getFileNameNoEx(redFile.getName()) + ".zip";
                    Message message;    //消息传递实例
                    String bytePwd = null;   //获取字节密码
                    //提示1:
                    message = new Message();
                    message.obj = "正在解压中,建议不要中途退出....";
                    handler.sendMessage(message);
                    //1.获取文件
//                    FileZipUtil.zipFile(redPath, BasDataUtil.getEncryptionPath() + "/" + BasDataUtil.FILE_NAME_TEM);
                    final InputStream inputStream = new FileInputStream(redPath);
                    //返回自己定义的文件名即可
                    final OutputStream outputStream = new FileOutputStream(new File(BasDataUtil.getDecryptionPath() + "/" + outFileName));
                    //2.获取密码并进行比较
                    while ((len = inputStream.read(temBuf)) != -1) {
                        //获取密码并操作
                        String s_pwd = new String(temBuf);
                        bytePwd = FileZipUtil.getFilePwd(s_pwd.split(BasDataUtil.PWD_HE)[1]);
                        if (!redPwd.equals(bytePwd)) {
                            //密码不正确
                            //(1).删除临时文件
                            File temFile = new File(BasDataUtil.getDecryptionPath() + "/" + outFileName);
                            if (temFile.exists()) {
                                temFile.delete();
                            }
                            //(2).告诉用户密码不正确
                            message = new Message();
                            message.what = LOADING_NOT;
                            message.obj = "密码错误!";
                            handler.sendMessage(message);
                            return;
                        }
                        break;
                    }
                    //2.修改文件：进行解密处理
                    //提示2:
                    message = new Message();
                    message.obj = "正在解密中，文件越大解密越久，请耐心等待...";
                    handler.sendMessage(message);
                    while ((len = inputStream.read(buf)) != -1) {
                        sleep(1);
                        //加密3：进行加密算法
                        for (int i = 0; i < buf.length; i++) {
                            if (i % 2 == 0) {
                                buf[i] = (byte) (buf[i] - (10 + Integer.parseInt(bytePwd.charAt(0) + "")));
                            } else {
                                buf[i] = (byte) (buf[i] - (Integer.parseInt(bytePwd.charAt(bytePwd.length() - 1) + "")));
                            }
                        }
                        //写入加密后的文件
                        outputStream.write(buf, 0, len);
                        //记录加载的长度
                        pro += 1024;
                        //进行消息传递，并以进度条显示
                        message = new Message();
                        message.what = LOADING_PRO;
                        message.arg1 = pro;
                        handler.sendMessage(message);
                    }
                    //出了while就是加密完成，关闭输入流
                    inputStream.close();
                    outputStream.close();
                    //3.解压文件获取源文件
                    FileZipUtil.Unzip(BasDataUtil.getDecryptionPath() + "/" + outFileName, BasDataUtil.getDecryptionPath());
//                    4.删除压缩包
                    File temFile = new File(BasDataUtil.getDecryptionPath() + "/" + outFileName);
                    if (temFile.exists()) {
                        temFile.delete();
                    }
                    message = new Message();
                    message.what = LOADING_OK;
                    handler.sendMessage(message);
                    Log.d(BasDataUtil.LOG_TOAST, "解密完成");
                } catch (Exception e) {
                    Message message = new Message();
                    message.what = LOADING_NOT;
                    message.obj = "文件没有解密过或文件已经损坏!";
                    handler.sendMessage(message);
                    Log.d(BasDataUtil.LOG_TOAST, "解密过程错误:" + e.toString());
                }
            }
        }.start();
        return true;
    }


}
